﻿//----------------------------------------------------------------------------
// Copyright (c) Pavel Tishkin 2012-2013.
//
// You must not remove this notice, or any other, from this software.
//----------------------------------------------------------------------------

namespace Lib.Dxp.Core


type Seq = 
    static member headOrDefault (xs : 'a seq) =
        if Seq.isEmpty xs 
            then Unchecked.defaultof<_>
            else Seq.take 1 xs |> Seq.head

    static member exclude f xs  = Seq.filter (f >> not) xs

    static member indexed xs    = Seq.mapi (fun i e -> (i, e)) xs

    static member filteri f xs  = xs |> Seq.indexed |> Seq.filter f 

    static member mapJoin f (sep : string) xs   = xs |> Seq.map f    |> sep.join 
    static member mapReduce fmap faggr xs       = xs |> Seq.map fmap |> Seq.reduce faggr





module List = 
    let headOrDefault (xs : 'a list) =
        match xs with
        | []     ->  Unchecked.defaultof<_>
        | h :: _ -> h

    let singleton e                 = [e]

    let indexed xs                  = List.mapi (fun i e -> (i, e)) xs

    let filteri f xs                = xs |> indexed |> List.filter f 

    let mapJoin f (sep : string) xs   = xs |> List.map f    |> sep.join 
    let mapReduce fmap faggr xs       = xs |> List.map fmap |> List.reduce faggr



//  Tuple extender
//      toList  :  (a, b, c, .... ) -> obj list option
//    fromList  : obj list -> boxed (a, b, c, .... )

module Tuple =
    open Microsoft.FSharp.Reflection
    let toList t = 
        if FSharpType.IsTuple(t.GetType()) 
            then FSharpValue.GetTupleFields t |> Array.toList |> Some
            else None
    
    let fromList l =
        let l' = List.toArray l
        let types = l' |> Array.map (fun o -> o.GetType())
        let tupleType = FSharpType.MakeTupleType types
        FSharpValue.MakeTuple (l' , tupleType)



[<AutoOpenAttribute>]
module NetCollections = 
    let netdict()       = System.Collections.Generic.Dictionary()
    let netlist(xs)     = System.Collections.Generic.List(xs : 'a seq)

    let choose  f xs    = Seq.choose    f xs
    let collect f xs    = Seq.collect   f xs
    let exclude f xs    = Seq.filter    (f >> not) xs
    let exists  f xs    = Seq.exists    f xs
    let filter  f xs    = Seq.filter    f xs
    let iter    f xs    = Seq.iter      f xs
    let iter2   f xs ys = Seq.iter2     f xs ys
    let iteri   f xs    = Seq.iteri     f xs
    let map     f xs    = Seq.map       f xs
    let map2    f xs ys = Seq.map2      f xs ys
    let mapi    f xs    = Seq.mapi      f xs
    let reduce  f xs    = Seq.reduce    f xs

    let takeHead xs     = Seq.headOrDefault xs
    let toArray  xs     = Seq.toArray       xs 
    let toList   xs     = Seq.toList        xs

    let toTwinsArray xs = xs |> map (fun e -> [| e; e |]) 

